package org.hfy.collections.helper;

import org.hfy.Constants;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 非终结符
 * @Author: Takagi
 * @date: 2023/4/23
 */
public class NonTerminator {
    public Symbol name;
    public List<SymbolString> equalList = new LinkedList<>();
    public Set<Symbol> First = new HashSet<>();
    public Set<Symbol> Follow = new HashSet<>();

    public SymbolString getFirstEqual() {
        return this.equalList.get(0);
    }

    public NonTerminator(Symbol name) {
        this.name = name;
    }

    /*
     * @Author Takagi
     * @Description: 更新 Follow 集合
     * @date: 2023/4/25
     * @param symbol
     * @return * @return boolean 若更新后集合大小发生变化，return true
     **/
    public boolean updateFollowSet(Symbol symbol) {
        int size = this.Follow.size();
        this.Follow.add(symbol);
        return size != this.Follow.size();
    }

    /*
     * @Author Takagi
     * @Description: 更新 Follow 集合
     * @date: 2023/4/25
     * @param followSet
     * @return * @return boolean 若更新后集合大小发生变化，return true
     **/
    public boolean updateFollowSet(Set<Symbol> followSet) {
        int size = this.Follow.size();
        this.Follow.addAll(followSet.stream().filter(item -> !Constants.isEpsilon(item)).collect(Collectors.toSet()));
        return size != this.Follow.size();
    }

    /*
     * @Author Takagi
     * @Description: 判断能否推导出 epsilon
     * @date: 2023/4/25
     * @param
     * @return * @return boolean
     **/
    public boolean canDeriveEpsilon() {
        for (SymbolString symbolString : this.equalList) {
            if (Constants.isEpsilon(symbolString.getFirstSymbol())) {
                return true;
            }
        }
        return false;
    }


    @Override
    public boolean equals(Object other) {
        if (!(other instanceof NonTerminator)) return false;
        return ((NonTerminator) other).name.content.equals(this.name.content);
    }

    @Override
    public int hashCode() {
        return this.name.hashCode();
    }

    @Override
    public String toString() {
        return this.name.content;
    }
}
